#!/bin/sh
# With some bashisms

rnd32(){
    printf "%d" $(printf "0x%x%x" $RANDOM $RANDOM)
}

#funcs="pow_2_2 pow_2_32 rshift lshift xor and rrot"
funcs="pow_2_2 pow_2_32 rshift lshift or or2 and and2 xor xor2 rrot"

export TIMEFORMAT="%3R"
for fn in $funcs ; do
    case $fn in
	pow_2_2) body="y=2^2"; factor=".02" ;;
	pow_2_32) body="y=2^32"; factor=".02" ;;
	rshift)
	    body="
y = g($(rnd32),1)
y = g($(rnd32),2)
y = g($(rnd32),3)
y = g($(rnd32),7)
y = g($(rnd32),10)
y = g($(rnd32),13)
y = g($(rnd32),17)
y = g($(rnd32),18)
y = g($(rnd32),19)
y = g($(rnd32),22)
y = g($(rnd32),25)"
	    factor="1" ;;
	lshift)
	    body="
y = f($(rnd32),31)
y = f($(rnd32),30)
y = f($(rnd32),29)
y = f($(rnd32),25)
y = f($(rnd32),22)
y = f($(rnd32),19)
y = f($(rnd32),15)
y = f($(rnd32),14)
y = f($(rnd32),13)
y = f($(rnd32),10)
y = f($(rnd32),7)"
	    factor="1" ;;
	xor)
	    body="
y = x($(rnd32),$(rnd32))
y = x($(rnd32),$(rnd32))
y = x($(rnd32),$(rnd32))
y = x($(rnd32),$(rnd32))
y = x($(rnd32),$(rnd32))
y = x($(rnd32),$(rnd32))
y = x($(rnd32),$(rnd32))
y = x($(rnd32),$(rnd32))
y = x($(rnd32),$(rnd32))
y = x($(rnd32),$(rnd32))"
	    factor="10" ;;
	xor2)
	    body="
y = y($(rnd32),$(rnd32))
y = y($(rnd32),$(rnd32))
y = y($(rnd32),$(rnd32))
y = y($(rnd32),$(rnd32))
y = y($(rnd32),$(rnd32))
y = y($(rnd32),$(rnd32))
y = y($(rnd32),$(rnd32))
y = y($(rnd32),$(rnd32))
y = y($(rnd32),$(rnd32))
y = y($(rnd32),$(rnd32))"
	    factor="10" ;;
	and)
	    body="
y = a($(rnd32),$(rnd32))
y = a($(rnd32),$(rnd32))
y = a($(rnd32),$(rnd32))
y = a($(rnd32),$(rnd32))
y = a($(rnd32),$(rnd32))
y = a($(rnd32),$(rnd32))
y = a($(rnd32),$(rnd32))
y = a($(rnd32),$(rnd32))
y = a($(rnd32),$(rnd32))
y = a($(rnd32),$(rnd32))"
	    factor="10" ;;
	and2)
	    body="
y = b($(rnd32),$(rnd32))
y = b($(rnd32),$(rnd32))
y = b($(rnd32),$(rnd32))
y = b($(rnd32),$(rnd32))
y = b($(rnd32),$(rnd32))
y = b($(rnd32),$(rnd32))
y = b($(rnd32),$(rnd32))
y = b($(rnd32),$(rnd32))
y = b($(rnd32),$(rnd32))
y = b($(rnd32),$(rnd32))"
	    factor="10" ;;
	or)
	    body="
y = o($(rnd32),$(rnd32))
y = o($(rnd32),$(rnd32))
y = o($(rnd32),$(rnd32))
y = o($(rnd32),$(rnd32))
y = o($(rnd32),$(rnd32))
y = o($(rnd32),$(rnd32))
y = o($(rnd32),$(rnd32))
y = o($(rnd32),$(rnd32))
y = o($(rnd32),$(rnd32))
y = o($(rnd32),$(rnd32))"
	    factor="10" ;;
	or2)
	    body="
y = p($(rnd32),$(rnd32))
y = p($(rnd32),$(rnd32))
y = p($(rnd32),$(rnd32))
y = p($(rnd32),$(rnd32))
y = p($(rnd32),$(rnd32))
y = p($(rnd32),$(rnd32))
y = p($(rnd32),$(rnd32))
y = p($(rnd32),$(rnd32))
y = p($(rnd32),$(rnd32))
y = p($(rnd32),$(rnd32))"
	    factor="10" ;;
	rrot)
	    body="
y = r($(rnd32),1)
y = r($(rnd32),2)
y = r($(rnd32),3)
y = r($(rnd32),7)
y = r($(rnd32),10)
y = r($(rnd32),13)
y = r($(rnd32),17)
y = r($(rnd32),18)
y = r($(rnd32),19)
y = r($(rnd32),22)
y = r($(rnd32),25)"
	    factor="11" ;;
    esac
    printf "%12s: " "$fn"
    time bc <<EOF
scale = 0
z = 2^32
define p(x,y){           /* plus modulo 2^32 */
  scale=0; return (x + y) % z; }
define g(x,n){           /* bitwise rightshift */
  scale=0; return x / 2^n; }
define f(x,n){           /* bitwise leftshift */
  scale=0; return (x * 2^n) % z; }
define q(x){             /* log2 */
  auto r, s
  s = scale; scale = 5
  r = l(x) / l(2);
  scale = s; return r; }
define n(x){             /* bitwise NOT */
  return z - 1 - x; }
define a(x,y){           /* bitwise AND */
  auto t, i
  if(x<y) { t = x; x = y; y = t; }  /* ensure x>=y */
  t = 0
  for (i=0; i<32; ++i) {
    t += (g(x,i) % 2) * (g(y,i) % 2) * 2^i
  }
  return t; }
define b(x,y){           /* bitwise AND */
  auto t, i, a, b, r
  if(x<y) { t = x; x = y; y = t; }  /* ensure x>=y */
  t = 0; a = x; b = y; r = 1
  for (i=0; i<32; ++i) {
    t += (a % 2) * (b % 2) * r
    r *= 2; a /= 2; b /= 2
  }
  return t; }
define o(x,y){           /* bitwise OR */
  auto t, i, z, w
  if(x<y) { t = x; x = y; y = t; }  /* ensure x>=y */
  t = 0
  for (i=0; i<32; ++i) {
    z = g(x,i) % 2
    w = g(y,i) % 2
    t += ((z + w + z*w) % 2) * 2^i
  }
  return t; }
define p(x,y){           /* bitwise OR (2) */
  auto t, i, z, w, r, a, b
  if(x<y) { t = x; x = y; y = t; }  /* ensure x>=y */
  t = 0; a = x; b = y; r = 1
  for (i=0; i<32; ++i) {
    z = a % 2; w = b % 2
    t += ((z + w + z*w) % 2) * r
    /* print "i=",i," z=",z," w=",w," a=",a," b=", b," t=",t," r=",r,"\n" */
    r *= 2; a /= 2; b /= 2
  }
  return t; }
define x(x, y){          /* bitwise XOR */
  auto t, i
  if(x<y) { t = x; x = y; y = t; }  /* ensure x>=y */
  t = 0
  for (i=0; i<32; ++i) {
    t += ((g(x,i) + g(y,i)) % 2) * 2^i
  }
  return t; }
define y(x, y){          /* bitwise XOR (2) */
  auto t, i, r, a, b, z, w
  if(x<y) { t = x; x = y; y = t; }  /* ensure x>=y */
  t = 0; a = x; b = y; r = 1
  for (i=0; i<32; ++i) {
    z = a % 2; w = b % 2
    t += ((z + w) % 2) * r
    /* print "i=",i," z=",z," w=",w," a=",a," b=", b," t=",t," r=",r,"\n" */
    r *= 2; a /= 2; b /= 2
  }
  return t; }
define r(x,n){           /* bitwise rightrotate */
  return p(f(x,32-n),g(x,n)); }

for (i=0; i<(2000/$factor); ++i) {
  $body
}
EOF
done
